package com.rit.secs;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.os.Vibrator;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class SECS extends Activity {
	
	// Registration Intent Information
	public static final String EXTRA_SENDER = "sender";
    public static final String EXTRA_APPLICATION_PENDING_INTENT = "app";
    public static final String REQUEST_UNREGISTRATION_INTENT = "com.google.android.c2dm.intent.UNREGISTER";
    public static final String REQUEST_REGISTRATION_INTENT = "com.google.android.c2dm.intent.REGISTER";
    public static final String GSF_PACKAGE = "com.google.android.gsf";
    public static final String EMAIL_OF_SENDER = "structureecs@gmail.com";
    
    // For the camera
    private Thread cameraThread;
    private static boolean refreshCamera = false;
    private boolean insideCameraThread = false;
	private Bitmap camMap;
	private static String SavePictureName = "SECS_Image_";
	private static int numPic = 0;
	private static int textColor = Color.WHITE;
	
	
	// Alert response time
	public static long responseWaitTime = 60000;
	
	// Alert refresh time
	public static long threadWaitTime = 5000;
	
	// The vibrator object
	private Vibrator v;
	
	// The counter
	private static CountDownTimer counter;
	private long currentTime;
	
	// Activity in background
	public static boolean amIActive;
	
	// Configuration File
	public static String CONFIG_FILE = "SECS_Configurations.txt";
	private static String RegistrationId = null;
	
	// The resonse time text
	private static TextView counterText;
	
	private static Button grantButton;
	private static Button denyButton;
	private static Button snapButton;
	
	private void takeAPicture() {
	    
	    try {
	    	System.out.println("Inside take a picture");
	    	ImageView camImage = (ImageView)findViewById(R.id.webCam);
	    	String picName = SavePictureName + numPic + ".jpg";
	        
	    	// Get the path to the picture directory on the SD card
	        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
	        File file = new File(path, picName);
	        
	        // Make sure the Pictures directory exists.
	        path.mkdirs();

	        // Create a BitMap object of the image to be worked with
		    Bitmap bm = ((BitmapDrawable)(camImage.getDrawable())).getBitmap();
	        OutputStream fOut = new FileOutputStream(file);
	                
	        // Use the compress method on the BitMap object to write image to the OutputStream
	        bm.compress(CompressFormat.JPEG, 90, fOut);
	        
	        fOut.flush();
	        fOut.close();
	        
	        
	        // Tell the media scanner about the new file so that it is
	        // immediately available to the user.
	        MediaScannerConnection.scanFile(this,
	                new String[] { file.toString() }, null,
	                new MediaScannerConnection.OnScanCompletedListener() {
	            public void onScanCompleted(String path, Uri uri) {
	            }
	        });
	        
	        // Increment the picture number
	        numPic++;
	        
	    } catch (IOException e) {
	    	e.printStackTrace();
	        // Unable to create file, likely because external storage is not currently mounted.
	    	Toast.makeText(getApplicationContext(), "Picture not saved. Unable to find external storage.", Toast.LENGTH_LONG).show();
	    }
	    
	}
	
	private void readRegistrationIdFromFile() {
		try {
			InputStream instream = openFileInput(CONFIG_FILE);
    		BufferedReader input = new BufferedReader(new InputStreamReader(instream));
    		try {
    			String line = input.readLine();
    			while(line != null) {
    				System.out.println("Reading... " + line);
    				if(line.startsWith("RegistrationId=", 0)) {
    					RegistrationId = line.substring(15);
    					System.out.println("Just got RegistratioId of = " + RegistrationId);
    				}
    				line = input.readLine();
    			}
    		} 
    		finally {
    			input.close();
    			instream.close();
    		}
		}
		catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	private void registerC2DM() {
		Thread registerThread = new Thread() {
			public void run() {
				C2DM();
			}
		};
		registerThread.start();
	}
	
	private void C2DM() { 
		Intent registrationIntent = new Intent(REQUEST_REGISTRATION_INTENT);
        registrationIntent.setPackage(GSF_PACKAGE);
        registrationIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT, PendingIntent.getBroadcast(this, 0, new Intent(), 0));
        registrationIntent.putExtra(EXTRA_SENDER, EMAIL_OF_SENDER);
        com.rit.secs.SECS.this.startService(registrationIntent);
	}
	
	public Object onRetainNonConfigurationInstance() {
		System.out.println("Check onRetain");
		//System.out.println("refCam = " + refreshCamera);
		Object [] retainList = new Object[7];
		ImageView camImage = (ImageView)findViewById(R.id.webCam);
		final Bitmap map = ((BitmapDrawable)(camImage.getDrawable())).getBitmap();
		if(map.isRecycled()) {
			retainList[0] = null;
		}
		else {
			retainList[0] = map;
		}
		final Boolean grantEnable = grantButton.isEnabled();
		retainList[1] = grantEnable;
		final Boolean denyEnable = denyButton.isEnabled();
		retainList[2] = denyEnable;
		final Boolean snapEnable = snapButton.isEnabled();
		retainList[3] = snapEnable;
		final String textString = counterText.getText().toString();
		retainList[4] = textString;
		final long tempCounter = currentTime;
		retainList[5] = tempCounter;
		final Boolean inCamThread = insideCameraThread;
		retainList[6] = inCamThread;
		
		return retainList;
	}
	
	private void createTimer(long duration) {
		currentTime = duration;
		counter = new CountDownTimer(duration, 1000) {

		     public void onTick(long millisUntilFinished) {
		    	 currentTime -= 1000;
		    	 int remainingTime = (int)(millisUntilFinished / 1000);
		    	 
		    	 counterText.setText("Remaining response time: " + remainingTime);
		    	 if(remainingTime <= 20 && remainingTime > 10) {
		    		 counterText.setTextColor(Color.YELLOW);
		    		 textColor = Color.YELLOW;
		    	 }
		    	 else if(remainingTime <= 10) {
		    		 counterText.setTextColor(Color.RED);
		    		 textColor = Color.RED;
		    	 }
		     }

		     
		     public void onFinish() {
		    	 System.out.println("done!");
		    	 grantButton.setEnabled(false);
		    	 denyButton.setEnabled(false);
		    	 counterText.setTextColor(Color.RED);
		    	 textColor = Color.RED;
		    	 counterText.setText("Access Denied");
		    	 refreshCamera = false;
		    	 Toast.makeText(getApplicationContext(), "Response timed out. Entry access denied.", Toast.LENGTH_LONG).show();
		     }
		  }.start();
	}
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState);
        System.out.println("Check OnCreate()");
        setContentView(R.layout.main);
        
        v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        
        
        
        // Read configuration file
        System.out.println("What is the registrationID? = " + RegistrationId);
        if(RegistrationId == null) {
	        System.out.println("Reading config file....");
	        readRegistrationIdFromFile();
        }
        
        
        // Start Registration for first time
        if(RegistrationId == null){
			System.out.println("Reg ID = " + RegistrationId);
			registerC2DM();	
        }
        else {
        	
        	//registerC2DM();
        	System.out.println("Reg ID = " + RegistrationId);
        	ServerComm.setRegistrationID(RegistrationId);
        }
        
        
        grantButton = (Button) findViewById(R.id.grantButton);
        grantButton.setOnClickListener(new OnClickListener() {
        	public void onClick(View v) {
        		ServerComm.grantAccess();
        		grantButton.setEnabled(false);
        		denyButton.setEnabled(false);
        		counter.cancel();
        		counterText.setTextColor(Color.GREEN);
        		textColor = Color.GREEN;
        		currentTime = 0L;
        		counterText.setText("Access Granted");
        		refreshCamera = false;
        	}
        });
        
        
        denyButton = (Button) findViewById(R.id.denyButton);
        denyButton.setOnClickListener(new OnClickListener() {
        	public void onClick(View v) {
        		ServerComm.denyAccess();
        		System.out.println("DENY");
        		denyButton.setEnabled(false);
        		grantButton.setEnabled(false);
        		counterText.setTextColor(Color.RED);
        		textColor = Color.RED;
        		currentTime = 0L;
        		counterText.setText("Access Denied");
        		counter.cancel();
        		refreshCamera = false;
        	}
        });
        
        snapButton = (Button) findViewById(R.id.snapButton);
        snapButton.setOnClickListener(new OnClickListener() {
        	public void onClick(View v) {
        		takeAPicture();
        	}
        });
        
        
        counterText = (TextView)findViewById(R.id.counterText);
        
        // Reload picture & camera on orientation change
        final Object changes = getLastNonConfigurationInstance();
        Object[] changeList = (Object[]) changes; 
        
        if(changeList != null) {
    		
    		// changeList[0] - The camera image
    		Bitmap cameraPhoto = (Bitmap) changeList[0];
	        System.out.println("Configuration Changed!");
	        if (cameraPhoto != null) {
	        	ImageView camImage = (ImageView)findViewById(R.id.webCam);
	        	camImage.setImageBitmap(cameraPhoto);
	        }
	        
	        // changeList[1] - The grant enable status
	        Boolean grantStatus = (Boolean) changeList[1];
    		grantButton.setEnabled(grantStatus.booleanValue());
	        
	        // changeList [2] - The deny enable status
    		Boolean denyStatus = (Boolean) changeList[2];
     		denyButton.setEnabled(denyStatus.booleanValue());
     		
			// changeList [3] - The snap enable status
     		Boolean snapStatus = (Boolean) changeList[3];
     		snapButton.setEnabled(snapStatus.booleanValue());
     		
			// changeList [4] - The counter text string
     		String text = (String) changeList[4];
     		counterText.setText(text);
     		
			// changeList [5] - The time remaining in the count down timer
     		currentTime = ((Long) changeList[5]).longValue();
     		if(currentTime > 0L) {
     			createTimer(currentTime);
     		}
     		
     		// The camera thread
     		insideCameraThread = ((Boolean) changeList[6]).booleanValue();
     		if(insideCameraThread) { 
     			refreshCamera = true;
     			startCameraThread();
     		}
     		
     		// The text color
     		counterText.setTextColor(textColor);
        }
        
        
        Intent intent = getIntent();
        if(intent != null) {
    		System.out.println("onCreate Action = " + intent.getAction());
    		if(intent.getAction().equals("POPUP")) {
    			refreshCamera = true;
    			startCameraThread();
    			grantButton.setEnabled(true);
    			denyButton.setEnabled(true);
    			createTimer(responseWaitTime);
    			counterText.setTextColor(Color.GREEN);
    			textColor = Color.GREEN;
    		}	
    	}
    }
   
    protected void onStart() {
    	super.onStart();
    	amIActive = true;
    }
    
    protected void onResume() {
    	super.onResume();
    	System.out.println("Check onResume()");
    }
    
    protected void onStop() {
    	super.onStart();
    	amIActive = false;
    	refreshCamera = false;
    	System.out.println("Check onStop()");
    }
    
    public void onNewIntent(Intent intent) {
    	System.out.println("Inside onNewIntent");
    	
    	if(intent != null) {
    		System.out.println("Action = " + intent.getAction());
    		if(intent.getAction().equals("CAMERA")) {
    			v.vibrate(500L);
    			//MediaPlayer mp = MediaPlayer.create(this, R.raw.knockknock);
    		    //mp.start();
    			refreshCamera = true;
    			startCameraThread();
    			grantButton.setEnabled(true);
    			denyButton.setEnabled(true);
    			createTimer(responseWaitTime);
    			counterText.setTextColor(Color.GREEN);
    			textColor = Color.GREEN;
    			
    		}
    		else if(intent.getAction().equals("POPUP")) {
    			refreshCamera = true;
    			startCameraThread();
    			grantButton.setEnabled(true);
    			denyButton.setEnabled(true);
    			createTimer(responseWaitTime);
    			counterText.setTextColor(Color.GREEN);
    			textColor = Color.GREEN;
    			
    		}
    		else if(intent.getAction().equals("REGISTRATION")) {
    			
    			Bundle extras = intent.getExtras();
    			if(extras !=null) {
    				RegistrationId = extras.getString("Registration");
    				System.out.println("Registration = " + RegistrationId);
    				writeConfigFile();
    			}
    		}
    		else if(intent.getAction().equals("ALERT_CANCELED")) {
    			Bundle extras = intent.getExtras();
    			if(extras !=null) {
    				String reason = extras.getString("Reason");
    				System.out.println("Reason = " + reason);
    				System.out.println("Do we have an ongoing alert? = " + refreshCamera);
    				// If we have an alert onging:
    				
    				if(counter != null) counter.cancel();
    				counterText.setText("Alert Canceled");
    				counterText.setTextColor(Color.WHITE);
    				textColor = Color.WHITE;
    				grantButton.setEnabled(false);
    				denyButton.setEnabled(false);
    				refreshCamera = false;
    				insideCameraThread = false;
    				Toast.makeText(getApplicationContext(), "Alert Canceled: " + reason, Toast.LENGTH_LONG).show();
    				
    			}
    		}
    	}
    }
    

    
    public void onDestroy() {
    	super.onDestroy();
    	System.out.println("Destroying Application!");
    	if(counter != null) counter.cancel();
    	if(cameraThread != null) cameraThread.interrupt();
    	refreshCamera = false;
    	insideCameraThread = false;
    }
    
    private void writeConfigFile() {
    	System.out.println("Inside writeConfigFile");
    	try {
    		String config = "RegistrationId="+RegistrationId+"\n";
    		System.out.println("Writing to file = " + config);
    		FileOutputStream fos = openFileOutput(CONFIG_FILE, Context.MODE_PRIVATE);
	    	fos.write(config.getBytes());
	    	fos.close();
	    } catch(IOException e) {
    		e.printStackTrace();
	    }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }
    
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        case R.id.configuration:
        	refreshCamera = false;
        	Intent i = new Intent(this, com.rit.secs.Configuration.class);
        	i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        	startActivity(i); 
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    
    
    public void startCameraThread() {
    	
    	cameraThread = new Thread(new Runnable() {
    		public void run() {
    			final ImageView camImage = (ImageView)findViewById(R.id.webCam);
    	    	System.out.println("connect camera thread");
    			while(refreshCamera) {
    				insideCameraThread = true;
    				camMap = ServerComm.loadImageFromCamera();    
    				camImage.post(new Runnable() {
    					public void run() {
    						if(camMap != null) {
    						//if(!camMap.isRecycled()) {
    							camImage.setImageBitmap(camMap);	
    							camImage.postInvalidate();
    							if(!snapButton.isEnabled()) snapButton.setEnabled(true);
							}
    					}	
    				});	
    					

					try {
						Thread.sleep(threadWaitTime);
					} catch(InterruptedException e) {
						e.printStackTrace();	
					}
    			}
    			insideCameraThread = false;
    		}
    	});
    	cameraThread.start();
    }
    
}
